home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Moscow ML 1.42 / src / compiler / Sigmtch.sml < prev    next >
Encoding:
Text File  |  1997-08-18  |  15.7 KB  |  470 lines  |  [TEXT/R*ch]

  1. (* Sigmtch.sml *)
  2.  
  3. open List Fnlib Mixture Const Prim Lambda Globals Units Types;
  4. open Front Back Emit_phr;
  5.  
  6. (* Signature matching *)
  7.  
  8. fun lookupSig_TyEnv (sign : CSig) id =
  9.   Hasht.find (#uTyEnv sign) id
  10.   handle Subscript =>
  11.     (msgIBlock 0;
  12.      errPrompt "Type "; msgString id;
  13.      msgString
  14.        " is specified in the signature but not defined in the unit body";
  15.      msgEOL();
  16.      msgEBlock();
  17.      raise Toplevel)
  18. ;
  19.  
  20. fun lookupSig_VarEnv (sign : CSig) id =
  21.   Hasht.find (#uVarEnv sign) id
  22.   handle Subscript =>
  23.     (msgIBlock 0;
  24.      errPrompt "Value "; msgString id;
  25.      msgString
  26.        " is specified in the signature but not defined in the unit body";
  27.      msgEOL();
  28.      msgEBlock();
  29.      raise Toplevel)
  30. ;
  31.  
  32. fun lookupSig_cBas (sign : CSig) id =
  33.   Hasht.find (#uConBasis sign) id
  34.   handle Subscript =>
  35.     (msgIBlock 0;
  36.      errPrompt "Value "; msgString id;
  37.      msgString
  38.        " is specified in the signature but not defined in the unit body";
  39.      msgEOL();
  40.      msgEBlock();
  41.      raise Toplevel)
  42. ;
  43.  
  44. fun errorImplMismatch id =
  45. (
  46.   msgIBlock 0;
  47.   errPrompt "Mismatch between the specification of the value ";
  48.   msgString id; msgEOL();
  49.   errPrompt "in the signature and its implementation in the unit body";
  50.   msgEOL();
  51.   msgEBlock();
  52.   raise Toplevel
  53. );
  54.  
  55. fun errorConImplMismatch id =
  56. (
  57.   msgIBlock 0;
  58.   errPrompt "Mismatch between the specification of the value constructor ";
  59.   msgString id; msgEOL();
  60.   errPrompt "in the signature and its implementation in the unit body";
  61.   msgEOL();
  62.   msgEBlock();
  63.   raise Toplevel
  64. );
  65.  
  66. fun errorExConImplMismatch id =
  67. (
  68.   msgIBlock 0;
  69.   errPrompt "Mismatch between the specification of the exception constructor ";
  70.   msgString id; msgEOL();
  71.   errPrompt "in the signature and its implementation in the unit body";
  72.   msgEOL();
  73.   msgEBlock();
  74.   raise Toplevel
  75. );
  76.  
  77. fun mkTypeFcnOfTyName (tn : TyName) =
  78.   let val vs = newTypeVars (#tnArity (!(#info tn))) in
  79.     TYPEts(vs, type_con (map TypeOfTypeVar vs) tn)
  80.   end
  81. ;
  82.  
  83. fun applyRea (tyname : TyName) ts =
  84.   case #tnStr(!(#info tyname)) of
  85.       NILts => type_con ts tyname
  86.     | TYPEts(pars, body) => fatalError "applyRea"
  87.     | DATATYPEts _ => type_con ts tyname
  88.     | REAts tn =>
  89.         let val arity = List.length ts
  90.             val {info=ref{tnArity, tnStr, ...}, ...} = tn
  91.         in
  92.           if tnArity <> arity then
  93.             fatalError "applyRea"
  94.           else ();
  95.           case tnStr of
  96.               NILts => type_con ts tn
  97.             | TYPEts(pars, body) =>
  98.                 type_subst (zip2 pars ts) body
  99.             | DATATYPEts _ => type_con ts tn
  100.             | REAts _ => fatalError "applyRea"
  101.         end
  102. ;
  103.  
  104. fun expandRea UE tau =
  105.   case normType tau of
  106.     VARt var =>
  107.       (lookup var UE
  108.        handle Subscript => fatalError "expandRea: Unknown variable")
  109.   | ARROWt(t,t') =>
  110.       ARROWt(expandRea UE t, expandRea UE t')
  111.   | CONt(ts, tn) =>
  112.       applyRea tn (map (expandRea UE) ts)
  113.   | RECt rt =>
  114.       let val {fields=fs, rho=rho} = !rt in
  115.         RECt (ref{fields=map_fields (expandRea UE) fs, rho=rho})
  116.       end
  117. ;
  118.  
  119. fun newParTypeVar () =
  120.   mkTypeVar false false false 0
  121. ;
  122.  
  123. fun newHardTypeVar () =
  124.   let val tv = mkTypeVar false false false 0 in
  125.     setTvKind tv (Explicit "");
  126.     tv
  127.   end;
  128.  
  129. fun isTypeFcnEqu vs' tau' vs tau =
  130.   let val ts = map (fn _ => TypeOfTypeVar(newHardTypeVar())) vs
  131.       val UE = zip2 vs ts
  132.       val tau0 = expandRea UE tau
  133.       val UE' = zip2 vs' ts
  134.       val tau'0 = type_subst UE' tau'
  135.   in
  136.     (unify tau'0 tau0; true)
  137.     handle Unify _ => false
  138.   end
  139. ;
  140.  
  141. fun matchDatatype (tyname : TyName) (CE : ConEnv) (CE' : ConEnv) =
  142.   let val domCE  = map (fn gci => #id(#qualid gci)) CE
  143.       val domCE' = map (fn gci => #id(#qualid gci)) CE'
  144.   in
  145.     (* domCE' is non-empty, because `abstype' is not allowed *)
  146.     (* in signatures, and "primitive" types are represented  *)
  147.     (* as NILts. *)
  148.     if domCE <> domCE' then (
  149.       msgIBlock 0;
  150.       errPrompt "Realization mismatch: variant type constructor ";
  151.       msgString (#id (#qualid tyname)); msgEOL();
  152.       errPrompt "has specification and realization that differ"; msgEOL();
  153.       errPrompt "in the names and/or the order of value constructors";
  154.       msgEOL();
  155.       msgEBlock();
  156.       raise Toplevel)
  157.     else ();
  158.     (* We don't have to compare the types of constructors here, *)
  159.     (* because they will be compared as values. Note that all *)
  160.     (* constructors are visible, for redefining values in signatures *)
  161.     (* is not allowed. *)
  162.     ()
  163.   end;
  164.  
  165. fun refresh0HardTypeVar (var : TypeVar) =
  166.   let val {tvEqu, tvImp, ...} = !var
  167.       val tv = mkTypeVar tvEqu tvImp false 0
  168.   in
  169.     setTvKind tv (Explicit "");
  170.     tv
  171.   end;
  172.  
  173. fun refresh0TypeVar (var : TypeVar) =
  174.   let val {tvEqu, tvImp, ...} = !var
  175.   in
  176.     mkTypeVar tvEqu tvImp false 0
  177.   end;
  178.  
  179. fun matchTypeSchemes id infSc specSc =
  180.   let
  181.     val TypeScheme{tscParameters=vs, tscBody=tau} = specSc
  182.     val ts = map (fn v => TypeOfTypeVar(refresh0HardTypeVar v)) vs
  183.     val UE = zip2 vs ts
  184.     val tau0 = expandRea UE tau
  185.     val TypeScheme{tscParameters=vs', tscBody=tau'} = infSc
  186.     val ts' = map (fn v => TypeOfTypeVar(refresh0TypeVar v)) vs'
  187.     val UE' = zip2 vs' ts'
  188.     val tau'0 = type_subst UE' tau'
  189.   in
  190.     unify tau'0 tau0
  191.     handle Unify _ =>
  192.       (let
  193.          val ts = map TypeOfTypeVar vs
  194.          val UE = zip2 vs ts
  195.          val tau0 = expandRea UE tau
  196.        in
  197.          msgIBlock 0;
  198.          errPrompt "Type mismatch: value identifier "; msgString id;
  199.          msgString " in the signature has type"; msgEOL();
  200.          errPrompt "  "; printType tau0; msgEOL();
  201.          errPrompt "whereas its implementation in the unit's body has type";
  202.          msgEOL();
  203.          errPrompt "  "; printScheme infSc; msgEOL();
  204.          msgEBlock();
  205.          raise Toplevel
  206.        end)
  207.   end;
  208.  
  209. fun realizeTyName (infTyName : TyName) (specTyName : TyName) =
  210.   let val {info=ref infInfo, ...} = infTyName
  211.       val {info=ref specInfo, qualid={id, ...}} = specTyName
  212.   in
  213.     if #tnArity specInfo  <> #tnArity infInfo then (
  214.       msgIBlock 0;
  215.       errPrompt "Arity mismatch: type constructor ";
  216.       msgString id; msgString " is specified as having arity ";
  217.       msgInt (#tnArity specInfo); msgEOL();
  218.       errPrompt "but declared as having arity ";
  219.       msgInt (#tnArity infInfo); msgString " in the unit's body";
  220.       msgEOL();
  221.       msgEBlock();
  222.       raise Toplevel)
  223.     else ();
  224.     case #tnEqu specInfo of
  225.         REFequ =>
  226.           if #tnEqu infInfo <> REFequ then (
  227.             msgIBlock 0;
  228.             errPrompt "Type constructor "; msgString id;
  229.             msgString " is specified as `prim_EQtype',";
  230.             msgEOL();
  231.             errPrompt "but isn't realized as a `prim_EQtype'";
  232.             msgEOL();
  233.             msgEBlock();
  234.             raise Toplevel)
  235.           else ()
  236.       | TRUEequ =>
  237.           if #tnEqu infInfo = FALSEequ then (
  238.             msgIBlock 0;
  239.             errPrompt "Type constructor "; msgString id;
  240.             msgString " is specified as admitting equality,";
  241.             msgEOL();
  242.             errPrompt "but its realization doesn't admit equality";
  243.             msgEOL();
  244.             msgEBlock();
  245.             raise Toplevel)
  246.           else ()
  247.       | FALSEequ =>
  248.           ();
  249.     case #tnStr specInfo of
  250.         NILts => setTnStr (#info specTyName) (REAts infTyName)
  251.       | TYPEts _ => ()
  252.       | DATATYPEts _ => ()
  253.       | REAts _ => fatalError "realizeTyName"
  254.   end;
  255.  
  256. fun checkRealization (inferredSig : CSig) (specSig : CSig)
  257.                      (infTyName : TyName) (specTyName : TyName) =
  258.   let val {info=ref infInfo, ...} = infTyName
  259.       val {info=ref specInfo, qualid={id, ...}} = specTyName
  260.   in
  261.     case #tnStr specInfo of
  262.         NILts => fatalError "checkRealization"
  263.       | TYPEts(vs, tau) =>
  264.           (case #tnStr infInfo of
  265.                NILts =>
  266.                  (msgIBlock 0;
  267.                   errPrompt "Realization mismatch: type constructor ";
  268.                   msgString id; msgString " is specified"; msgEOL();
  269.                   errPrompt "as a type abbreviation,"; msgEOL();
  270.                   errPrompt "but implemented as a primitive type"; msgEOL();
  271.                   msgEBlock();
  272.                   raise Toplevel)
  273.              | TYPEts(vs', tau') =>
  274.                  if not(isTypeFcnEqu vs' tau' vs tau) then (
  275.                    msgIBlock 0;
  276.                    errPrompt "Realization mismatch: type constructor ";
  277.                    msgString id; msgString " is bound"; msgEOL();
  278.                    errPrompt "to non-equivalent type abbreviations"; msgEOL();
  279.                    errPrompt "in the signature and in the unit body"; msgEOL();
  280.                    msgEBlock();
  281.                    raise Toplevel)
  282.                  else ()
  283.              | DATATYPEts _ =>
  284.                  (msgIBlock 0;
  285.                   errPrompt "Realization mismatch: type constructor ";
  286.                   msgString id; msgString " is specified"; msgEOL();
  287.                   errPrompt "as a type abbreviation,"; msgEOL();
  288.                   errPrompt "but implemented as a variant type"; msgEOL();
  289.                   msgEBlock();
  290.                   raise Toplevel)
  291.              | REAts tn' => fatalError "checkRealization")
  292.       | DATATYPEts dt =>
  293.           let val CE = findConstructors specSig dt in
  294.             case #tnStr infInfo of
  295.                 NILts =>
  296.                   (msgIBlock 0;
  297.                    errPrompt "Realization mismatch: type constructor ";
  298.                    msgString id;
  299.                    msgString " is specified as a variant type,"; msgEOL();
  300.                    errPrompt "but implemented as a primitive type"; msgEOL();
  301.                    msgEBlock();
  302.                    raise Toplevel)
  303.               | TYPEts(vs', tau') =>
  304.                   (msgIBlock 0;
  305.                    errPrompt "Realization mismatch: type constructor ";
  306.                    msgString id;
  307.                    msgString " is specified as a variant type,"; msgEOL();
  308.                    errPrompt "but implemented as a type abbreviation"; msgEOL();
  309.                    msgEBlock();
  310.                    raise Toplevel)
  311.               | DATATYPEts dt' =>
  312.                   let val CE' = findConstructors inferredSig dt'
  313.                   in matchDatatype specTyName CE CE' end
  314.               | REAts tn' => fatalError "checkRealization"
  315.           end
  316.       | REAts _ => ()
  317.   end;
  318.  
  319. fun exportValAsVal os (infStatus : ConStatus) (specStatus : ConStatus) =
  320.   let val lam =
  321.     Lprim(Pset_global (#qualid specStatus, 0),
  322.             [Lprim(Pget_global (#qualid infStatus, 0), [])])
  323.   in emit_phrase os (compileLambda true lam) end
  324. ;
  325.  
  326. fun exportPrimAsVal os (pi : PrimInfo) (specStatus : ConStatus) =
  327.   let val lam =
  328.     Lprim(Pset_global (#qualid specStatus, 0), [trPrimVar (#primOp pi)])
  329.   in emit_phrase os (compileLambda true lam) end
  330. ;
  331.  
  332. fun exportConAsVal os (ci : ConInfo) (specStatus : ConStatus) =
  333.   let val lam =
  334.     Lprim(Pset_global (#qualid specStatus, 0), [trConVar ci])
  335.   in emit_phrase os (compileLambda true lam) end
  336. ;
  337.  
  338. fun exportExConAsVal os (ei : ExConInfo) (specStatus : ConStatus) =
  339.   let val lam =
  340.     Lprim(Pset_global (#qualid specStatus, 0), [trTopExConVar ei])
  341.   in emit_phrase os (compileLambda true lam) end
  342. ;
  343.  
  344. fun checkHomeUnits infQual specQual id thing =
  345.   if specQual <> infQual then (
  346.     msgIBlock 0;
  347.     errPrompt "Specified signature expects the ";
  348.     msgString thing; msgString " ";
  349.     msgString id; msgString " to be defined"; msgEOL();
  350.     errPrompt "in the unit "; msgString specQual;
  351.     msgString " but it is defined in the unit ";
  352.     msgString infQual; msgEOL();
  353.     msgEBlock();
  354.     raise Toplevel)
  355.   else ();
  356. ;
  357.  
  358. fun matchIdStatus os infStatus specStatus =
  359.   let val {qualid=infQualid, info=infInfo} = infStatus
  360.       val {qualid=specQualid, info=specInfo} = specStatus
  361.       val {qual=infQual, ...} = infQualid
  362.       val {qual=specQual, id=id} = specQualid
  363.   in
  364.     case specInfo of
  365.         VARname ovltype =>
  366.           (* checkHomeUnits infQual specQual id "value"; *)
  367.           (case infInfo of
  368.                VARname ovltype' =>
  369.                  (if ovltype <> ovltype' then errorImplMismatch id
  370.                   else ();
  371.                   if specQual <> infQual then
  372.                     exportValAsVal os infStatus specStatus
  373.                   else ())
  374.              | PRIMname pi' =>
  375.                    exportPrimAsVal os pi' specStatus
  376.              | CONname ci' =>
  377.                    exportConAsVal os ci' specStatus
  378.              | EXNname ei' =>
  379.                    exportExConAsVal os ei' specStatus
  380.              | REFname => errorImplMismatch id)
  381.       | PRIMname pi =>
  382.           (* checkHomeUnits infQual specQual id "prim_value"; *)
  383.           (case infInfo of
  384.                VARname ovltype' => errorImplMismatch id
  385.              | PRIMname pi'=>
  386.                  if pi <> pi' then errorImplMismatch id else ()
  387.              | CONname ci' => errorImplMismatch id
  388.              | EXNname ei' => errorImplMismatch id
  389.              | REFname => errorImplMismatch id)
  390.       | CONname ci =>
  391.           (* checkHomeUnits infQual specQual id "value constructor"; *)
  392.           (case infInfo of
  393.                VARname ovltype' => errorImplMismatch id
  394.              | PRIMname pi' => errorImplMismatch id
  395.              | CONname ci' =>
  396.                  if #conArity(!ci) <> #conArity(!ci')
  397.                  orelse #conIsGreedy(!ci) <> #conIsGreedy(!ci')
  398.                  orelse #conTag(!ci) <> #conTag(!ci')
  399.                  orelse #conSpan(!ci) <> #conSpan(!ci')
  400.                  then errorConImplMismatch id
  401.                  else ()
  402.              | EXNname ei' => errorImplMismatch id
  403.              | REFname => errorImplMismatch id)
  404.       | EXNname ei =>
  405.           (checkHomeUnits infQual specQual id "exception";
  406.            case infInfo of
  407.                VARname ovltype' => errorImplMismatch id
  408.              | PRIMname pi' => errorImplMismatch id
  409.              | CONname ci' => errorImplMismatch id
  410.              | EXNname ei' =>
  411.                  if #exconArity(!ei) <> #exconArity(!ei')
  412.                  orelse #exconIsGreedy(!ei) <> #exconIsGreedy(!ei')
  413.                  then errorExConImplMismatch id
  414.                  else ()
  415.              | REFname => errorImplMismatch id)
  416.       | REFname =>
  417.           (case infInfo of
  418.                VARname ovltype' => errorImplMismatch id
  419.              | PRIMname pi' => errorImplMismatch id
  420.              | CONname ci' => errorImplMismatch id
  421.              | EXNname ei' => errorImplMismatch id
  422.              | REFname => ())
  423.   end
  424. ;
  425.  
  426. fun matchStamps (inferredSig : CSig) (specSig : CSig) =
  427.   Hasht.apply
  428.     (fn uname => fn stamp =>
  429.       let val stamp' = Hasht.find (#uMentions inferredSig) uname in
  430.         if stamp' <> stamp then (
  431.           msgIBlock 0;
  432.           errPrompt "The signature of "; msgString uname;
  433.           msgString " has changed, while "; msgString (#uName specSig);
  434.           msgString ".sig depends on it."; msgEOL();
  435.           errPrompt "Please, recompile "; msgString (#uName specSig);
  436.           msgString ".sig, before compiling "; msgString (#uName specSig);
  437.           msgString ".sml."; msgEOL();
  438.           msgEBlock();
  439.           raise Toplevel)
  440.         else ()
  441.       end
  442.       handle Subscript => ())
  443.     (#uMentions specSig)
  444. ;
  445.  
  446. fun matchSignature os (inferredSig : CSig) (specSig : CSig) =
  447. (
  448.   (* Matching stamps of mentioned signatures *)
  449.   matchStamps inferredSig specSig;
  450.   (* Type realization. *)
  451.   Hasht.apply (fn id => fn specTyName =>
  452.       realizeTyName (lookupSig_TyEnv inferredSig id) specTyName)
  453.     (#uTyEnv specSig);
  454.   Hasht.apply (fn id => fn specTyName =>
  455.       checkRealization inferredSig specSig
  456.                        (lookupSig_TyEnv inferredSig id) specTyName)
  457.     (#uTyEnv specSig);
  458.   (* Matching value types *)
  459.   Hasht.apply (fn id => fn specSc =>
  460.       matchTypeSchemes id (lookupSig_VarEnv inferredSig id) specSc)
  461.     (#uVarEnv specSig);
  462.   (* Status matching. *)
  463.   (* This may cause some code to be generated, *)
  464.   (* if a primitive function or a value constructor is *)
  465.   (* exported as a value. *)
  466.   Hasht.apply (fn id => fn specStatus =>
  467.       matchIdStatus os (lookupSig_cBas inferredSig id) specStatus)
  468.     (#uConBasis specSig)
  469. );
  470.